package com.ruoyi.project.websocket.component;

import com.alibaba.fastjson.JSON;
import com.ruoyi.project.im.domain.ImMessage;
import com.ruoyi.project.im.domain.ImTemporaryMessage;
import com.ruoyi.project.im.service.IImMessageService;
import com.ruoyi.project.im.service.IImTemporaryMessageService;
import com.ruoyi.project.im.service.impl.ImMessageServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/im/{userId}")
@Component
@Slf4j
public class SocketServer {
    public static Map<String, Session> userSessionMap = new ConcurrentHashMap<>();

    private static IImMessageService messageService;

    private static IImTemporaryMessageService temporaryMessageService;

    @Autowired
    public void setMessageService(ImMessageServiceImpl imMessageService) {
        SocketServer.messageService = imMessageService;
    }

    @Autowired
    public void setMessageService(IImTemporaryMessageService imTemporaryMessageService) {
        SocketServer.temporaryMessageService = imTemporaryMessageService;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        try {
            userSessionMap.put(userId, session);
            log.info("用户ID为{}连接成功！", userId);
        } catch (Exception e) {
            log.error("用户ID为{}连接失败！", userId, e);
        }
    }

    @OnClose
    public void onClose(Session session, @PathParam("userId") String userId) {
        try {
            userSessionMap.remove(userId);
            log.info("用户ID为{}下线-------------", userId);
        } catch (Exception e) {
            log.error("onClose异常-------------", e);
        }
    }

    @OnError
    public void onError(Session session, Throwable error, @PathParam("userId") String userId) {
        userSessionMap.remove(userId);
    }

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("userId") Long userId) {
        log.info("收到用户ID为{}得消息{}", userId, message);
        if ("heartbeat".equals(message)) {
            this.sendMessageByUserId(userId, "OK");
        }
    }

    public void sendMessageByUserId(Long userId, String message) {
        try {
            ImMessage model = JSON.parseObject(message, ImMessage.class);
            ImTemporaryMessage temporaryMessage=new ImTemporaryMessage();
            for (String key : userSessionMap.keySet()) {
                if (key.equals(String.valueOf(userId))) {
                    this.sendMessage(message, userSessionMap.get(key));
                    log.info("向用户ID为{}发送消息{}", userId, message);
                    return;
                }
            }
            temporaryMessage.setMessageId(model.getId());
            temporaryMessage.setSenderId(model.getSenderId());
            temporaryMessage.setReceiverId(model.getReceiverId());
            temporaryMessageService.insertImTemporaryMessage(temporaryMessage);
            log.info("向未在线的用户ID为{}发送消息{}", userId, message);
        } catch (Exception e) {
            log.error("向用户ID为{}发送消息失败---", userId, e);
        }
    }

    public void broadcastMessage(String message) {
        try {
            for (String key : userSessionMap.keySet()) {
                this.sendMessage(message, userSessionMap.get(key));
            }
        } catch (Exception e) {
            log.error("群发消息失败------", e);
        }
    }

    public void sendMessage(String message, Session toSession) {
        try {
            if (toSession.isOpen()) {
                synchronized (toSession) {
                    toSession.getAsyncRemote().sendText(message);
                }
            }
        } catch (Exception e) {
            log.error("发送消息失败---------", e);
        }
    }
}
